package com.sunfeng.elasticsearch.elastic.compound;

import com.sunfeng.elasticsearch.utils.ClientUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.DisMaxQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.IOException;

/**
 * @Author : 孙峰
 * @Description:
 *  返回一个或者多个包装查询的文档，成为查询子句或者子句
 *  如果返回的文档与多个查询子句匹配，则dis_max查询会为该文档分配任何匹配子句中的最高相关性分数，并为任何其他匹配的子查询加上一个平局增量。
 *
 *  queries:(必须的，查询对象数组) 包含一个或者多个查询子句。返回的文档必须与这些查询中的一个或者多个匹配，如果一个文档匹配多个查询，Elasticsearch 使用最高相关性分数。
 *
 *  tie_breaker: （可选，float）之间的浮点数0，1.0用于增加匹配多个查询子句的文档的相关性分数。默认为0.0.
 *
 *  您可以使用该tie_breaker值为在多个字段中包含相同术语的文档分配更高的相关分数.
 *  如果文档匹配多个子句，则dis_max查询计算文档的相关性分数，如下所示：
 *  1、从得分最高的匹配子句中获取相关性得分。
 *  2、将任何其他匹配子句的分数乘以该tie_breaker值。
 *  3、将最高分数添加到相乘分数中。
 *
 *  如果该tie_breaker值大于0.0，则所有匹配的子句都计数，但得分最高的子句计数最多
 *
 * @Date : 2022/5/7  14:18
 */
public class DistinctionMaxQuery {
    public static void main(String[] args) throws IOException {
        // 创建客户端对象
        RestHighLevelClient client = null;
        try {
            client = ClientUtils.getInstance();
            distinctionMaxQuery(client);
        } finally {
            assert client != null;
            client.close();
        }
    }

    /**
     *  析取最大值查询
     * @param client
     */
    private static void distinctionMaxQuery(RestHighLevelClient client) throws IOException {
        SearchRequest searchRequest = new SearchRequest().indices("blogs");

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        DisMaxQueryBuilder disMaxQuery = QueryBuilders.disMaxQuery();
        disMaxQuery.add(QueryBuilders.matchQuery("title","Quick pets"));
        disMaxQuery.add(QueryBuilders.matchQuery("body","Quick pets"));
        disMaxQuery.tieBreaker(0.2f);

        sourceBuilder.query(disMaxQuery);

        searchRequest.source(sourceBuilder);
        SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);

        SearchHits hits = search.getHits();
        System.out.println(hits.getTotalHits());
        for (SearchHit hit : hits) {
            System.out.println(hit.getScore());
            System.out.println(hit.getSourceAsMap());
        }
    }
}
